package com.liujit.upms.service.impl;

import cn.hutool.core.collection.CollectionUtil;
import cn.hutool.core.convert.Convert;
import cn.hutool.core.lang.tree.Tree;
import cn.hutool.core.lang.tree.TreeNodeConfig;
import cn.hutool.core.lang.tree.TreeUtil;
import cn.hutool.core.util.StrUtil;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.enums.SqlKeyword;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.liujit.common.constants.ColumnConstant;
import com.liujit.common.constants.GlobalConstant;
import com.liujit.common.domain.params.BaseParams;
import com.liujit.common.domain.result.PageBean;
import com.liujit.common.exception.BusinessException;
import com.liujit.common.exception.DataNotFoundException;
import com.liujit.common.utils.CommonUtil;
import com.liujit.common.utils.DozerConvertor;
import com.liujit.common.utils.Pagination;
import com.liujit.upms.domain.model.SysMenu;
import com.liujit.upms.domain.model.SysPermission;
import com.liujit.upms.domain.model.SysRoleMenu;
import com.liujit.upms.domain.params.SysMenuParams;
import com.liujit.upms.domain.query.SysMenuQuery;
import com.liujit.upms.domain.query.SysMenuTreeQuery;
import com.liujit.upms.domain.result.SysMenuResult;
import com.liujit.upms.mapper.SysMenuMapper;
import com.liujit.upms.service.SysMenuService;
import com.liujit.upms.service.SysPermissionService;
import com.liujit.upms.service.SysRoleMenuService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import java.util.ArrayList;
import java.util.List;

/**
 * @Description 系统菜单Service实现类
 * @Author liujun
 * @Date 2021-07-02 14:59:44
 */
@Service
public class SysMenuServiceImpl extends ServiceImpl<SysMenuMapper, SysMenu> implements SysMenuService {

    private SysRoleMenuService sysRoleMenuService;

    private SysPermissionService sysPermissionService;

    @Autowired
    public void setSysRoleMenuService(SysRoleMenuService sysRoleMenuService) {
        this.sysRoleMenuService = sysRoleMenuService;
    }

    @Autowired
    public void setSysPermissionService(SysPermissionService sysPermissionService) {
        this.sysPermissionService = sysPermissionService;
    }

    @Override
    public PageBean<SysMenuResult> getPage(SysMenuQuery query) {
        if (StrUtil.isNotBlank(query.getSortName()) && StrUtil.isNotBlank(query.getSortOrder())) {
            query.setSortName(ColumnConstant.SEQ);
            query.setSortOrder(SqlKeyword.ASC.getSqlSegment());
        }
        Page<SysMenu> page = Pagination.page(query);
        LambdaQueryWrapper<SysMenu> wrapper = new LambdaQueryWrapper();
        if (StrUtil.isNotBlank(query.getName())) {
            wrapper.like(SysMenu::getName, query.getName());
        }
        if (query.getPid() != null) {
            wrapper.eq(SysMenu::getPid, query.getPid());
        }
        if (query.getEnabled() != null) {
            wrapper.eq(SysMenu::getEnabled, query.getEnabled());
        }
        if (query.getStartTime() != null) {
            wrapper.ge(SysMenu::getCreateTime, query.getStartTime());
        }
        if (query.getEndTime() != null) {
            wrapper.le(SysMenu::getCreateTime, query.getEndTime());
        }
        IPage<SysMenu> iPage = super.page(page, wrapper);
        return PageBean.page(iPage, SysMenuResult.class);
    }

    @Override
    public Boolean save(SysMenuParams params) {
        SysMenu entity = DozerConvertor.convertor(params, SysMenu.class);
        // 添加
        if (params.getId() == null) {
            entity.setEnabled(GlobalConstant.ENABLED_YES);
            Boolean res = super.save(entity);
            // 添加超级管理员菜单权限
            sysRoleMenuService.save(new SysRoleMenu() {{
                setRoleId(Convert.toLong(GlobalConstant.SUPER_ROLE_ID));
                setMenuId(entity.getId());
            }});
            return res;
        } else {
            SysMenu sysMenu = super.getById(params.getId());
            if (sysMenu == null) {
                throw new DataNotFoundException();
            }
            return super.updateById(entity);
        }
    }

    @Override
    public SysMenuResult get(Long id) {
        SysMenu sysMenu = super.getById(id);
        if (sysMenu == null) {
            throw new DataNotFoundException();
        }
        return DozerConvertor.convertor(sysMenu, SysMenuResult.class);
    }

    @Override
    public SysMenuResult getDetail(Long id) {
        SysMenuResult result = this.get(id);
        // 查询父id名称
        if (result.getPid() > 0) {
            result.setPname(this.getNameById(result.getPid()));
        }
        return result;
    }

    @Override
    public Boolean del(BaseParams params) {
        SysMenu sysMenu = super.getById(params.getId());
        if (sysMenu == null) {
            throw new DataNotFoundException();
        }
        // 查询节点是否有数据
        LambdaQueryWrapper<SysMenu> wrapper = new LambdaQueryWrapper<>();
        wrapper.eq(SysMenu::getPid, params.getId());
        Integer count = super.count(wrapper);
        if (count > 0) {
            throw new BusinessException("菜单下有数据，不能删除");
        }
        // 如果是菜单，查询菜单下是否有权限
        if (GlobalConstant.MENU_TYPE_MENU.equals(sysMenu.getType())) {
            LambdaQueryWrapper<SysPermission> queryWrapper = new LambdaQueryWrapper<>();
            queryWrapper.eq(SysPermission::getMenuId, sysMenu.getId());
            count = sysPermissionService.count(queryWrapper);
            if (count > 0) {
                throw new BusinessException("菜单下有按钮，不能删除");
            }
        }
        // 删除超级管理员菜单权限
        LambdaQueryWrapper<SysRoleMenu> deleteWrapper = new LambdaQueryWrapper<>();
        deleteWrapper.eq(SysRoleMenu::getMenuId, params.getId());
        sysRoleMenuService.remove(deleteWrapper);
        return super.removeById(params.getId());
    }

    @Override
    public Boolean enabled(BaseParams params) {
        SysMenu sysMenu = super.getById(params.getId());
        if (sysMenu == null) {
            throw new DataNotFoundException();
        }
        return super.updateById(new SysMenu() {{
            setId(params.getId());
            setEnabled(GlobalConstant.ENABLED_YES);
        }});
    }

    @Override
    public Boolean disabled(BaseParams params) {
        SysMenu sysMenu = super.getById(params.getId());
        if (sysMenu == null) {
            throw new DataNotFoundException();
        }
        // 查询节点是否有数据
        LambdaQueryWrapper<SysMenu> wrapper = new LambdaQueryWrapper<>();
        wrapper.eq(SysMenu::getPid, sysMenu.getId());
        Integer count = super.count(wrapper);
        if (count > 0) {
            throw new BusinessException("菜单下有数据，不能禁用");
        }
        return super.updateById(new SysMenu() {{
            setId(params.getId());
            setEnabled(GlobalConstant.ENABLED_NO);
        }});
    }

    @Override
    public List<SysMenu> getByUserId(Long userId, boolean superAdmin) {
        List<SysMenu> sysMenuList;
        // 路由信息
        if (superAdmin) {
            LambdaQueryWrapper<SysMenu> wrapper = new LambdaQueryWrapper<>();
            wrapper.eq(SysMenu::getEnabled, GlobalConstant.ENABLED_YES);
            wrapper.orderByAsc(SysMenu::getSeq);
            sysMenuList = super.list(wrapper);
        } else {
            sysMenuList = super.baseMapper.selByUserId(userId);
        }
        return sysMenuList;
    }

    @Override
    public List<Tree<Long>> getTree(SysMenuTreeQuery query) {
        LambdaQueryWrapper<SysMenu> wrapper = new LambdaQueryWrapper();
        wrapper.orderByAsc(SysMenu::getSeq);
        if (StrUtil.isNotBlank(query.getName())) {
            wrapper.like(SysMenu::getName, query.getName());
        }
        if (query.getType() != null) {
            wrapper.eq(SysMenu::getType, query.getType());
        }
        if (query.getEnabled() != null) {
            wrapper.eq(SysMenu::getEnabled, query.getEnabled());
        }
        List<SysMenu> list = super.list(wrapper);
        // 配置树
        TreeNodeConfig config = new TreeNodeConfig();
        config.setParentIdKey("pid");
        config.setNameKey("name");
        config.setWeightKey("seq");
        // 排序字段
        return TreeUtil.build(list, 0L, config, (object, tree) -> {
            tree.putExtra("id", object.getId());
            tree.putExtra("pid", object.getPid());
            tree.putExtra("name", object.getName());
            tree.putExtra("type", object.getType());
        });
    }

    @Override
    public List<Long> getMenuIdByRoleId(Long roleId) {
        LambdaQueryWrapper<SysRoleMenu> wrapper = new LambdaQueryWrapper();
        wrapper.select(SysRoleMenu::getMenuId);
        wrapper.eq(SysRoleMenu::getRoleId, roleId);
        return sysRoleMenuService.listObjs(wrapper, item -> Convert.toLong(item));
    }

    @Override
    public Boolean modifyRoleMenu(Long roleId, List<Long> ids) {
        // 查询全部菜单
        LambdaQueryWrapper<SysMenu> wrapper = new LambdaQueryWrapper();
        wrapper.select(SysMenu::getId);
        wrapper.eq(SysMenu::getEnabled, GlobalConstant.ENABLED_YES);
        List<Long> menuIds = super.listObjs(wrapper, item -> Convert.toLong(item));
        // 删除现有角色菜单
        LambdaQueryWrapper<SysRoleMenu> removeWrapper = new LambdaQueryWrapper();
        removeWrapper.eq(SysRoleMenu::getRoleId, roleId);
        sysRoleMenuService.remove(removeWrapper);
        List<SysRoleMenu> list = new ArrayList<>();
        ids.forEach(item -> {
            if (CollectionUtil.contains(menuIds, item)) {
                list.add(new SysRoleMenu() {{
                    setRoleId(roleId);
                    setMenuId(item);
                }});
            }
        });
        // 添加
        return sysRoleMenuService.saveBatch(list);
    }

    @Override
    public List<Long> getRoleIdByUrlPermission(Long menuId, String urlPermission) {
        List<Long> roleIds = new ArrayList<>();
        // 查询当前菜单URL权限标识
        LambdaQueryWrapper<SysMenu> menuWrapper = new LambdaQueryWrapper();
        menuWrapper.select(SysMenu::getId, SysMenu::getUrlPermission);
        menuWrapper.eq(SysMenu::getId, menuId);
        menuWrapper.eq(SysMenu::getEnabled, GlobalConstant.ENABLED_YES);
        SysMenu sysMenu = super.getOne(menuWrapper);
        if (sysMenu != null) {
            boolean check = CommonUtil.checkContains(sysMenu.getUrlPermission(), urlPermission);
            // 当前地址存在该菜单下
            if (check) {
                // 查询菜单角色
                LambdaQueryWrapper<SysRoleMenu> queryWrapper = new LambdaQueryWrapper<>();
                queryWrapper.select(SysRoleMenu::getRoleId);
                queryWrapper.eq(SysRoleMenu::getMenuId, sysMenu.getId());
                List<Long> list = sysRoleMenuService.listObjs(queryWrapper, item -> Convert.toLong(item));
                roleIds.addAll(list);
            }
        }
        return roleIds;
    }

    @Override
    public String getNameById(Long id) {
        LambdaQueryWrapper<SysMenu> wrapper = new LambdaQueryWrapper<>();
        wrapper.select(SysMenu::getName);
        wrapper.eq(SysMenu::getId, id);
        return super.getObj(wrapper, item -> Convert.toStr(item));
    }
}
